#include <stdio.h>
#include <stdlib.h>
#include <string.h>

enum animal_kind{
	cat,
	brid,
	dog
};

// 封装, 动物抽象类
typedef struct animal {
	char name[16];	// 具体名字
	int kind;		// 什么种类
	int life;		// 寿命	
	void (*print) (void *t);	// 打印基本属性
	void (*set_name)(void *t, const char *name);	// 设置或修改名字
	void (*init)(void *t, const char *name, int kind, int life);	// 初始化基本属性
} animal_t;

typedef struct brid {
	animal_t animal;		// 继承动物抽象类	
	int fly_height;			// 飞行高度
	void (*introduce) (void *t);	// 详细介绍
} brid_t;

typedef struct panther {
	animal_t animal;		// 继承动物抽象类
	int run_speed;			// 奔跑速度
	void (*introduce) (void *t);	// 详细介绍
} panther_t;


/********************** 抽象类的通用接口函数 *********************************/
void animal_set_name(void *t, const char *name) {
	animal_t *me = (animal_t *)t;
	// 假设name长度不会超过16
	strcpy(me->name, name);
}

void animal_introduce(void *t) {
	animal_t *me = (animal_t *)t;
	printf("name:%s\n", me->name);
	printf("kind:%d\n", me->kind);
	printf("life:%d\n", me->life);	
}

void animal_init(void *t, const char *name, int kind, int life) {
	animal_t *me = (animal_t *)t;
	me->set_name = animal_set_name;	// 给函数指针赋予实体
	me->set_name(me, name);			// 调用方法
	me->kind = kind;
	me->life = life;
	me->print = animal_introduce;
}
/*------------------------------------------------------------------------*/


/********************** 具体类的接口函数实现 *********************************/
void brid_introduce(void *p) {
	struct brid *me = (struct brid *)p;
	printf("fly_height:%d\n",me->fly_height);
	printf("啄木鸟是属于森林的益鸟，它们是树木皮下害虫的天敌，\
	因其凿木的痕迹也可作为森林卫生采伐的指示剂，故有“森林医生”之称。\n");
}
void panther_introduce(void *p) {
	struct panther *me = (struct panther *)p;
	printf("run_speed:%d\n",me->run_speed);
	printf("美洲豹是生活在中南美洲的一种大型猫科动物。它身上的花纹比较像豹，\
	但整个身体的形状又更接近于虎。在猫科动物中，美洲豹的体型仅次于狮、虎。\n");
}
/*------------------------------------------------------------------------*/

int main()
{
	panther_t A;
	
	// 抽象类的属性和方法; 
	A.animal.init = animal_init;	// 给函数指针赋予实体, 才能进行调用
	A.animal.init(&A, "panther", cat, 16);	// 初始化基本属性: 名字, 种族, 寿命
	A.animal.set_name(&A, "panther 001");	// 修改名字

	// 具体类独有的属性和方法
	A.run_speed = 100;
	A.introduce = panther_introduce;	
	
	A.animal.print(&A);		// 打印基本属性
	A.introduce(&A);		// 打印详细介绍

	return 0;
}